const std = @import("std");
const string = @import("../string/string.zig");
const String = string.String;

pub const HttpMethod = enum {
    GET,
    POST,
    PUT,
    DELETE,
    HEAD,
    PATCH,
    OPTIONS,
    TRACE,
    CONNECT,
};

pub const Request = struct {
    method: HttpMethod,
    uri: String,
    ver: String,
    allocator: std.mem.Allocator,

    pub fn init(allocator: std.mem.Allocator, data: String) !Request {
        const temp = data.splitNum("\r\n", 2);

        defer string.freeStringArray(temp);
        if (temp.items.len > 0) {
            const line = temp.items[0];
            const word_list = line.split(" ");
            defer string.freeStringArray(word_list);
            if (word_list.items.len >= 2) {
                // method
                var method: HttpMethod = undefined;
                if (word_list.items[0].equalIgnoreCase("GET")) {
                    method = .GET;
                } else if (word_list.items[0].equalIgnoreCase("POST")) {
                    method = .POST;
                }
                var req = .{
                    .method = method,
                    .uri = String.init(allocator),
                    .ver = String.init(allocator),
                    .allocator = allocator,
                };

                // url
                try req.uri.pushBackStr(word_list.items[1]);
                try req.ver.pushBackStr(word_list.items[2]);
                return req;
            } else {
                return error.IceRunTimeError;
            }
        } else {
            return error.IceRunTimeError;
        }
    }

    pub fn deinit(self: Request) void {
        self.uri.deinit();
        self.ver.deinit();
    }

    pub fn toStr(self: Request) !String {
        var ret = String.init(self.allocator);
        try ret.pushBackFormat("{s} {s} {s}", .{ @tagName(self.method), self.uri.toStr(), self.ver.toStr() });
        return ret;
    }
};

// 提供静态文件
pub fn serveStaticFile(request: *std.http.Server.Request, abs_path: []const u8) !void {
    // 打开文件
    const file = std.fs.openFileAbsolute(abs_path, .{}) catch |err| {
        std.debug.print("catch std.fs.openFileAbsolute", .{});
        // 如果文件不存在，返回 404
        if (err == error.FileNotFound) {
            const head: std.http.Header = .{
                .name = "Content-Type",
                .value = "text/plain",
            };
            try request.respond("404 Not Found\n", .{
                .status = .not_found,
                .extra_headers = &[_]std.http.Header{head},
            });
            return;
        }
        return err;
    };
    defer file.close();

    var send_buffer: [4096]u8 = undefined;
    const file_stat = try file.stat();

    var response = request.respondStreaming(.{
        .content_length = file_stat.size,
        .send_buffer = &send_buffer,
        .respond_options = .{
            .status = .ok,
            .extra_headers = &.{
                // .{ .name = "Content-Type", .value = "application/octet-stream" }, // 二进制文件类型
                .{ .name = "Content-Type", .value = getMimeType(abs_path) }, // 二进制文件类型
                .{ .name = "Content-Disposition", .value = "inline; filename=\"index.html\"" }, // 提示客户端下载文件
            },
        },
    });

    var data_buffer: [4096]u8 = undefined;
    var remaining = file_stat.size;
    while (remaining > 0) {
        const read_size = @min(data_buffer.len, remaining); // 计算本次读取的大小
        const bytes_read = try file.read(data_buffer[0..read_size]);
        try response.writeAll(data_buffer[0..bytes_read]);
        remaining -= bytes_read;
    }
    response.flush() catch |err| {
        std.debug.print("{any}", .{err});
        return error.IceRunTimeError;
    };

    // // 设置响应头
    // server.status = .ok;
    // try server.headers.append("Content-Type", getMimeType(file_path));

    // // 发送文件内容
    // const file_size = try file.getEndPos();
    // var buffer: [4096]u8 = undefined;
    // var remaining = file_size;
    // while (remaining > 0) {
    //     const read_size = @min(buffer.len, remaining);
    //     const bytes_read = try file.read(buffer[0..read_size]);
    //     try server.writeAll(buffer[0..bytes_read]);
    //     remaining -= bytes_read;
    // }

    // try server.finish();
}

// 获取文件的 MIME 类型
fn getMimeType(file_path: []const u8) []const u8 {
    if (std.mem.endsWith(u8, file_path, ".html")) return "text/html";
    if (std.mem.endsWith(u8, file_path, ".css")) return "text/css";
    if (std.mem.endsWith(u8, file_path, ".js")) return "application/javascript";
    if (std.mem.endsWith(u8, file_path, ".png")) return "image/png";
    if (std.mem.endsWith(u8, file_path, ".jpg") or std.mem.endsWith(u8, file_path, ".jpeg")) return "image/jpeg";
    if (std.mem.endsWith(u8, file_path, ".gif")) return "image/gif";
    if (std.mem.endsWith(u8, file_path, ".svg")) return "image/svg+xml";
    if (std.mem.endsWith(u8, file_path, ".json")) return "application/json";
    return "application/octet-stream";
}
